/***************************************************************************
 *   This file is part of KLabeler                                         *
 *   Copyright (C) 2010 by Luca Bellonda                                   *
 *   lbellonda _at_ gmail.com                                              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include "KLabelerApplication.h"
#include "Utility.h"

#include <QIcon>
#include <QtDBus>

#include <KAction>
#include <KCrash>
#include <KCmdLineArgs>
#include <KAboutData>
#include <KLocale>
#include <KConfigGroup>
#include <QVector>

#include "klabeleradaptor.h"

#include <KXmlGuiWindow>
#include <KTextEdit>
#include "Configuration.h"
#include "lib/Config.h"

#include "ChooseProfile.h"

#define SOURCE_CLASS "KLabelerApplication"


namespace klabeler
{

KLabelerApplication::KLabelerApplication(int argc, char ** argv)
#ifdef  TAGGER_UNIQUE_APPL
        : KUniqueApplication(argc, argv)
#endif
{
#ifdef KTAGGER_TEST
    //chooseProfile( NULL, NULL );
    //testMessages();
#endif
    _controlWindow = NULL ;
    setUpLog();
    logger.info(&logParam, "klabeler started");
}

bool KLabelerApplication::event(QEvent * e)
{
#ifdef  TAGGER_UNIQUE_APPL
    return KUniqueApplication::event(e);
#else
    return KApplication::event(e);
#endif
}

bool KLabelerApplication::init()
{
    setQuitOnLastWindowClosed(false);
    connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanUpAboutToQuit()));
    KCrash::setFlags(KCrash::AutoRestart);

    if (!initInternals()) {
        logger.warning(&logParam, "init failed");
        return false;
    }

    new AppAdaptor(this);
    QDBusConnection dbus = QDBusConnection::sessionBus();
    dbus.registerObject(MAIN_DBUS_OBJECT, this);
    dbus.registerService("org.kde.klabeler");

    _addTags = new AddTags(this);
    if (NULL == _addTags) {
        logger.fatal(&logParam, "unable to create AddTags");
        return false;
    }

    KSharedConfigPtr    config = KSharedConfig::openConfig(CONFIG_COMPONENT);
    KConfigGroup        cfgGroup(config, CONFIG_GROUP_DEBUG);
    bool enabledWindow   = cfgGroup.readEntry(CONFIG_DEBUG_KEY_WINDOW, false);

    if (enabledWindow) {
        _controlWindow = new ControlWindow(this);
        if (NULL != _controlWindow) {
            connect(_controlWindow, SIGNAL(openOtherTags()), this, SLOT(assignOtherTagsTest()));
            connect(_controlWindow, SIGNAL(configure()), this, SLOT(configure()));
            connect(_controlWindow, SIGNAL(chooseProfile()), this, SLOT(chooseCurrentProfile()));
            connect(_controlWindow, SIGNAL(tagsProfile()), this, SLOT(tagsProfileTest()));
            _controlWindow->show();
        }
    }
    return true;
}

KLabelerApplication::~KLabelerApplication()
{
    if (NULL != _controlWindow) {
        delete _controlWindow ;
    }
    if (NULL != _addTags) {
        delete _addTags ;
    }
    logger.info(&logParam, "end");
}



void KLabelerApplication::setUpLog()
{
    logParam.source = SOURCE_CLASS ;
    /*logger = new TLogger( true, KTAGGER_LOG_TAG, NULL ) ;
    if( NULL == logger ) {
        return false;
    }
    return true;*/
}

bool KLabelerApplication::initInternals()
{
    if (!configurationManager.init()) {
        logger.warning(&logParam, " Configuration init failed");
        return false;

    }
    if (!nepomukManager.init()) {
        logger.warning(&logParam, " Nepomuk init failed");
        return false;
    }
    return true;
}

int KLabelerApplication::prova()
{
    logServiceStart("prova");
    logServiceEnd("prova", 2);
    return 2;
}

ConfigurationManager * KLabelerApplication::getConfigurationManager()
{
    return &configurationManager;
}

NepomukManager *KLabelerApplication::getNepomukManager()
{
    return &nepomukManager;
}

QString KLabelerApplication::getCurrentProfileName()
{
    QString name;
    bool isOk = true ;
    QString currentProfileId;
    if (configurationManager.getCurrentProfileId(currentProfileId)) {
        if (!currentProfileId.isEmpty()) {
            bool isOk = false ;
            TagProfile* profile = configurationManager.getProfile(currentProfileId);
            if (NULL != profile) {
                name = profile->getName();
                delete profile;
                isOk = true ;
            }
        }
    }
    if (!isOk) {
        Utility::error(NULL, i18n("Error reading curent profile"));
    }
    return name ;
}


bool KLabelerApplication::isProfileIdValid(const QString &id)
{
    return (!id.isEmpty() && (id != "0"));
}

TagProfile* KLabelerApplication::getCurrentProfile() // TODO: vedere di identificare l-attivita corrente
{
    TagProfile *result = NULL ;
    bool isOk = false ;
    QString currentProfileId;
    if (configurationManager.getCurrentProfileId(currentProfileId)) {
        QVector<TagProfile*> *profiles = configurationManager.getProfilesList();
        if (NULL != profiles) {
            isOk = true ;
            if (!isProfileIdValid(currentProfileId)) {
                // TODO prende il primo
                if (profiles->size() > 0) {
                    result = profiles->at(0);
                }
            } else {
                int size = profiles->size();
                for (int i = 0; i < size; i++) {
                    TagProfile* profile = profiles->at(i) ;
                    if (profile->getId() == currentProfileId) {
                        result = profile ;
                        break;
                    }
                }
            }
            int size = profiles->size();
            for (int i = 0; i < size; i++) {
                TagProfile* profile = profiles->at(i) ;
                if (profile != result) {
                    delete profile ;
                }
            }
            delete profiles;
        }
    }
    if (!isOk) {
        Utility::error(NULL, i18n("Error reading curent profile"));
    }
    return result ;
}


QStringList KLabelerApplication::getCurrentProfileTags(const QString &activityName, bool &isOk)
{
    QStringList result;
    isOk = false ;
    QString currentProfileId;
    if (configurationManager.getCurrentProfileId(currentProfileId)) {
        isOk = true ;
        if (isProfileIdValid(currentProfileId)) {
            result = configurationManager.getProfileTags(currentProfileId, isOk);
        } else {
            // look for profiles
            result = configurationManager.getActivityTags(activityName, isOk);
        }
    }
    if (!isOk) {
        Utility::error(NULL, i18n("Error reading tags of current activity "));
    }
    return result ;
}


//--------------------------------------------- SERVICES --------------------------------------

/**
  services exposed by application
  */

void KLabelerApplication::configure()
{
    logServiceStart("configure");
    showConfigurationDialog(this, NULL);
    emit configurationChanged();
    logServiceEnd("configure", 0);
}

bool KLabelerApplication::chooseCurrentProfile()
{
    bool isOk = false;
    logServiceStart("chooseCurrentProfile");
    if (chooseWorkingProfile(NULL, getCurrentProfileName(), this)) {
        emit configurationChanged();
        isOk = true;
    }
    logServiceEnd("chooseCurrentProfile", isOk ? 1 : 0);
    return isOk ;
}

/**
  * apply the profile to the resources
  */
bool KLabelerApplication::applyProfile(const QString &activityName, const QStringList &resources)
{
    logServiceStart("setTags");
    bool retCode = true;
    QStringList tags = getCurrentProfileTags(activityName, retCode);
    foreach(QString resource, resources) {
        if (!nepomukManager.addTagListToResource(resource, tags)) {
            retCode = false;
        }
    }
    logServiceEnd("setTags", retCode);
    return retCode;
}

/**
  * gets the tag list assigned to the activity
  */


QStringList KLabelerApplication::getActivityTags(const QString &activityName, bool &isOk)
{
    logServiceStart("getActivityTags");
    isOk = true;
    QStringList tags = getCurrentProfileTags(activityName, isOk);
    logServiceEnd("getActivityTags", isOk);
    return tags;
}

void KLabelerApplication::assignOtherTags(const QString &activityName, const QString resourcePath)
{
    logServiceStart("assignOtherTags");

    if (!_addTags->isVisible()) {
        QStringList currentProfileTags;
#ifndef USE_NEPOMUK
        currentProfileTags.append("Three - MOCKUP"); //TODO
        currentProfileTags.append("Four - MOCKUP");
#endif

        _addTags->setCurrentProfileTags(currentProfileTags);
        _addTags->setTargetResource(resourcePath);
        _addTags->go();
    }
    logServiceEnd("assignOtherTags", 0);
}

//--------------------------------------------- END SERVICES --------------------------------------


void KLabelerApplication::assignOtherTagsTest()
{
    assignOtherTags("", "/tmp");
}



void KLabelerApplication::logServiceStart(const QString &service)
{
    if (logger.isLoggable(TLogger::DEBUG)) {
        logParam.method = service ;
        logger.debug(&logParam, "start");
        logParam.method = "" ;
    }
}

void KLabelerApplication::logServiceEnd(const QString &service, const bool result)
{
    if (logger.isLoggable(TLogger::DEBUG)) {
        logParam.method = service ;
        logger.debug(&logParam, QString("end, result=%1").arg(result));
        logParam.method = "" ;
    }
}

void KLabelerApplication::logServiceEnd(const QString &service, const int result)
{
    if (logger.isLoggable(TLogger::DEBUG)) {
        logParam.method = service ;
        logger.debug(&logParam, QString("end, result=%1").arg(result));
        logParam.method = "" ;
    }
}

void KLabelerApplication::cleanUpAboutToQuit()
{
    logger.info(&logParam, "about to end");
}

void KLabelerApplication::testMessages()
{
    Utility::error(NULL, "prova errore");
    Utility::message(NULL, "prova info");
    Utility::askYN(NULL, "prova yn");
}

void KLabelerApplication::tagsProfileTest()
{
    QStringList resources;
    resources.append("/tmp");
    if (!applyProfile("one", resources)) {
        Utility::error(i18n("test failed"));
    }
}

}
